﻿using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Entities.ScreeningTool;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.ScreeningTool.Synchronization.Caches
{
    public class ResearchStatesCache : DictionaryCache<Guid, ResearchStates>
    {
        public ResearchStates GetResearchStates(Guid companyId) => GetValueOrEmpty(companyId, null);

        public bool IsResearchAvailable(Guid companyId, Func<ResearchStates, ResearchState> getResearchState)
        {
            var researchStates = GetResearchStates(companyId);

            if (researchStates == null)
                return false;

            var researchState = getResearchState?.Invoke(researchStates);
            return researchState == ResearchState.ResearchAvailable;
        }

        public IEnumerable<Guid> GetGccsCompanyIds()
            => dictionary.Where(x => x.Value.Gccs == ResearchState.ResearchAvailable).Select(x => x.Key);

        public IEnumerable<Guid> GetProductInvolvementCompanyIds()
            => dictionary.Where(x => x.Value.ProductInvolvement == ResearchState.ResearchAvailable).Select(x => x.Key);
    }

    public class ResearchStatesCacheLoader : ICacheLoader<ResearchStatesCache>
    {
        private readonly ResearchStatesCache cache;
        private readonly IMongoCollection<CorporateData> collection;

        public ResearchStatesCacheLoader(ResearchStatesCache cache, IMongoCollection<CorporateData> collection)
        {
            this.cache = cache;
            this.collection = collection;
        }

        public async Task LoadAsync(ClientFacingProduct clientFacingProduct)
        {
            var values = await collection
                .Find(_ => true)
                .Project(x => new
                {
                    x.Id,
                    ResearchStates = x.ToResearchStates(clientFacingProduct)
                })
                .ToListAsync()
                .ConfigureAwait(false);

            var items = values.ToDictionary(x => x.Id, x => x.ResearchStates);

            cache.AddItems(items);
        }
    }
}
